﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tetris
{
    internal class Game
    {
        //定义字段blockImageWidth，表明方块的子区域的宽度
        public const int blockImageWidth = 21;
        //定义字段blockImageHeight，表明方块的子区域的宽度
        public const int blockImageHeight = 21;
        //定义字段gameAreaWidth，表明游戏区域的宽度
        public const int blocksWidth = 10;
        //定义字段gameAreaHeight，表明游戏区域的高度
        public const int blocksHeight = 20;
        //定义Blocks，表明游戏区域的所有子区域，即游戏区域的所有方块
        private readonly int[,] blocks;
        //实例化Block类生成对象此方块thisBlock
        private Block thisBlock; 
        //定义字段lines，表明清除的满行数
        public int lines = 0;
        //实例化Block类生成对象续方块nextBlock
        private Block nextBlock; 
        //定义字段GameOver，表明游戏当前状态
        public bool GameOver = false;
        //定义字段score，表明分数
        public int score = 0;
        /// <summary>
        /// 定义构造函数 Game() ，初始化游戏区域，默认所有子区域当前状态均为无图片状态，需要续块
        /// </summary>
        public Game() 
        {
            blocks = new int[blocksWidth, blocksHeight];
            Clearblocks();
            NextBlock(); 
        }
        /// <summary>
        /// 定义方法Clearblocks()，默认所有子区域当前状态均为无图片状态即清空游戏区域的所有方块
        /// </summary>
        private void Clearblocks() 
        {
            for (int i = 0; i < blocksWidth; i++)
            {
                for (int j = 0; j < blocksHeight; j++)
                {
                    //所有子区域当前状态均为无图片状态
                    blocks[i, j] = 0;
                }
            }
        }
        /// <summary>
        /// 定义方法NextBlock()，生成此方块的续方块
        /// </summary>
        private void NextBlock()
        {
            //判断是否需要续块
            if (nextBlock != null)
            {
                //生成续块
                thisBlock = nextBlock;
            }
            else
            {
                //需要此块
                thisBlock = new Block();
            }
            //生成此块的续块
            nextBlock = new Block();
        }
        /// <summary>
        /// 定义方法Drawblocks(Graphics g)，绘制游戏区域
        /// </summary>
        /// <param name="g"></param>
        public void Drawblocks(Graphics g)
        {
            //获取子区域图片
            Image blockImage = Properties.Resources.block;
            for (int i = 0; i < blocksWidth; i++)
            {
                for (int j = 0; j < blocksHeight; j++)
                {
                    //判断子区域当前状态是否为有图片状态
                    if (blocks[i, j] == 1)
                    {
                        //绘制
                        Rectangle recblock = new Rectangle
                        {
                            Location = new Point(i * blockImageWidth, j * blockImageHeight)
,
                            Size = new Size(blockImageWidth, blockImageHeight)
                        };
                        g.DrawImage(blockImage, recblock);
                    }
                }
            }
        }
        /// <summary>
        /// 绘制方块此块
        /// </summary>
        /// <param name="g"></param>
        public void DrawthisBlock(Graphics g)
        {
            //判断是否需要绘制
            if (thisBlock != null) 
            {
                //绘制
                thisBlock.Draw(g);
            }
        }
        /// <summary>
        /// 绘制方块续块
        /// </summary>
        /// <param name="drawingSurface"></param>
        public void DrawNextBlock(Graphics drawingSurface)
        {
            //判断是否需要绘制
            if (nextBlock != null)
            {
                //绘制
                int thisLeft = nextBlock.Left;
                int thisTop = nextBlock.Top;
                nextBlock.Left = (6 - nextBlock.Width) / 2;
                nextBlock.Top = (6 - nextBlock.Height) / 2;
                nextBlock.Draw(drawingSurface);
                nextBlock.Left = thisLeft;
                nextBlock.Top = thisTop;
            }
        }
        /// <summary>
        /// 定义方法SaveBlock() ，存储此块
        /// </summary>
        private void SaveBlock() 
        {
            for (int i = 0; i < thisBlock.Width; i++)
            {
                for (int j = 0; j < thisBlock.Height; j++)
                {
                    int x, y;
                    x = thisBlock.Left + i;
                    y = thisBlock.Top + j;
                    if (thisBlock.block[i, j] == 1)
                    {
                        blocks[x, y] = 1;
                    }
                }
            }
            //检验是否满行
            CheckLines();
            //检验游戏是否结束
            if (CheckGame()) 
                GameOver = true;
        }
        /// <summary>
        /// 定义方法DownBlock()，下落此块
        /// </summary>
        /// <returns></returns>
        public bool DownBlock()
        {
            bool full = false;
            thisBlock.Top++;
            if ((thisBlock.Top + thisBlock.Height) > blocksHeight)
            {
                full = true; 
            }
            else 
            {
                for (int i = 0; i < thisBlock.Width; i++)
                {
                    for (int j = 0; j < thisBlock.Height; j++)
                    {
                        int x, y;
                        x = thisBlock.Left + i;
                        y = thisBlock.Top + j;
                        //判断是否与他块冲突
                        if ((thisBlock.block[i, j] == 1) && (blocks[x, y] == 1))
                        {
                            full = true;
                        }
                    }
                }
            }
            if (full)
            {
                thisBlock.Top--;
                //存储此块
                SaveBlock();     
                //生成续块
                NextBlock(); 
            }
            return full;
        }
        /// <summary>
        /// 定义方法RotatethisBlock()，旋转此块
        /// </summary>
        public void RotatethisBlock()
        {
            bool canRotate = true;
            int newWidth = 0;
            int newHeight = 0;
            int[,] newblock;
            newWidth = thisBlock.Height;
            newHeight = thisBlock.Width;
            newblock = new int[newWidth, newHeight];
            int x, y;
            if (((thisBlock.Left + newWidth) <= blocksWidth)
                && ((thisBlock.Top + newHeight) < blocksHeight))
            {
                for (int i = 0; i < thisBlock.Width; i++)
                {
                    for (int j = 0; j < thisBlock.Height; j++)
                    {
                        x = (thisBlock.Height - 1) - j;
                        y = i;
                        newblock[x, y] = thisBlock.block[i, j];
                        //判断旋转过程中给是否与他块冲突
                        if (newblock[x, y] == 1 && blocks[x + thisBlock.Left, y + thisBlock.Top] == 1)
                        {
                            canRotate = false;
                            return; 
                        }
                    }
                }
                //判断此块是否可以旋转
                if (canRotate)
                {
                    //旋转此块
                    thisBlock.Width = newWidth;
                    thisBlock.Height = newHeight;
                    thisBlock.block = newblock;
                }
            }
        }
        /// <summary>
        /// 定义方法MovethisBlock(bool left)，移动此块
        /// </summary>
        /// <param name="left"></param>
        public void MovethisBlock(bool left) 
        {
            bool canMove = true;
            //向左移动此块
            if (left) 
            {
                if (thisBlock.Left > 0)
                {
                    for (int i = 0; i < thisBlock.Width; i++)
                    {
                        for (int j = 0; j < thisBlock.Height; j++)
                        {
                            int fx, fy;
                            fx = thisBlock.Left + i;
                            fy = (thisBlock.Top + 1) + j;
                            //判断向左移动过程中是否与他块冲突
                            if ((thisBlock.block[i, j] == 1) && (blocks[(fx - 1), fy] == 1))
                            {
                                canMove = false;
                            }
                        }
                    }
                    if (canMove)
                    {
                        thisBlock.Left--;
                    }
                }
            }
            //向右移动此块
            else 
            {
                if ((thisBlock.Left + thisBlock.Width) < blocksWidth)
                {
                    for (int i = 0; i < thisBlock.Width; i++)
                    {
                        for (int j = 0; j < thisBlock.Height; j++)
                        {
                            int fx, fy;
                            fx = thisBlock.Left + i;
                            fy = (thisBlock.Top + 1) + j;
                            //判断向右移动过程中是否与他块冲突
                            if ((thisBlock.block[i, j] == 1) && (blocks[(fx + 1), fy] == 1))
                            {
                                canMove = false;
                            }
                        }
                    }
                    //判断是否可以移动
                    if (canMove)
                    {
                        //移动
                        thisBlock.Left++;
                    }
                }
            }
        }
        /// <summary>
        /// 定义方法CheckLines()，检验是否存在满行
        /// </summary>
        /// <returns></returns>
        private int CheckLines() 
        {
            int numLines = 0;
            int[] fullLines = new int[blocksHeight];
            for (int j = blocksHeight - 1; j > 0; j--) 
            {
                bool fullLine = true;
                for (int i = 0; i < blocksWidth; i++)
                {
                    if (blocks[i, j] == 0)
                    {
                        fullLine = false;
                        break;
                    }
                }
                //判断此行是否满行
                if (fullLine)
                {
                    numLines++;
                    fullLines[numLines] = j;
                }
            }
            //判断是否存在满行
            if (numLines > 0)
            {
                //筛选满行
                for (int i = 1; i <= numLines; i++)
                {
                    //消除满行
                    ClearLine(fullLines[i] + (i - 1));
                }
                //分数增加
                score += 5 * numLines * (numLines + 1);
                //满行数增加
                lines += numLines;
            }
            return numLines;
        }
        /// <summary>
        /// 定义方法ClearLine(int lineNumber)，消除已经存在的满行
        /// </summary>
        /// <param name="lineNumber"></param>
        private void ClearLine(int lineNumber)
        {
            for (int j = lineNumber; j > 0; j--)
            {
                for (int i = 0; i < blocksWidth; i++)
                {
                    blocks[i, j] = blocks[i, (j - 1)];
                }
            }
            for (int i = 0; i < blocksWidth; i++)
            {
                blocks[i, 0] = 0;
            }
        }
        /// <summary>
        /// 定义方法CheckGame() ，检验游戏是否结束
        /// </summary>
        /// <returns></returns>
        public bool CheckGame() 
        {
            if (thisBlock.Top == 0)
                return true;
            else
                return false;
        }
    }

}

